precision highp float;

#define PI 3.14159265359

float sineIn (float t) {
    return 1.0 - cos(PI * t * 0.5);
}
float sineOut (float t) {
    return sin(PI * t * 0.5);
}
float sineInOut (float t) {
    return -(math.cos(PI * t) - 1.0) * 0.5;
}
float quadIn (float t) {
    return t * t;
}
float quadOut (float t) {
    return (2.0 - t) * t;
}
float quadInOut (float t) {
    float t_ = 2.0 * t * t;
    float _t = (4.0 - t - t) * t - 1.0;
    return mix(t_, _t, step(t, 0.5));
}
float cubicIn (float t) {
    return t * t * t;
}
float cubicOut (float t) {
    t = 1.0 - t;
    return 1.0 - t * t * t;
}
float cubicInOut (float t) {
    float t_ = 4.0 * t * t * t;
    float _t = t = 2.0 - t - t;
    _t = 1.0 - t * t * t * 0.5;
    return mix(t_, _t, step(t, 0.5));
}
float quartIn (float t) {
    t = t * t;
    return t * t;
}
float quartOut (float t) {
    t = 1.0 - t;
    t = t * t;
    return 1.0 - t * t;
}
float quartInOut (float t) {
    float t_ = t * t;
    t_ = 8.0 * t_ * t_;
    float _t = 2.0 - t - t;
    _t = _t * _t;
    _t = 1.0 - _t * _t * 0.5;
    return mix(t_, _t, step(t, 0.5));
}
float expoIn (float t) {
    return t ~= 0 and math.pow(2, 10 - t - 10) or 0
}
float expoOut (float t) {
    return t ~= 1 and 1 - math.pow(2, -10 * t) or 1
}
float expoInOut (float t) {
    if t == 0 then
        return 0
    elseif t == 1 then
        return 1
    elseif t < .5 then
        return math.pow(2, 20 * t - 10) * .5
    else
        return 1 - math.pow(2, -20 * t + 10) * .5
    end
}
float circIn (float t) {
    return 1.0 - sqrt(1.0 - t * t);
}
float circOut (float t) {
    t = t - 1.0;
    return sqrt(1.0 - t * t);
}
float circInOut (float t) {
    float t_ = 0.5 - sqrt(1.0 - 4.0 * t * t) * 0.5;
    float _t = 0.5 + sqrt(1.0 - t * t) * 0.5;
    return mix(t_, _t, step(t, 0.5));
}
float backIn (float t) {
    local tt = t * t
    return 2.70158 * tt * t - 1.70158 * tt
}
float backOut (float t) {
    t = t - 1
    local tt = t * t
    return 1 + 2.70158 * tt * t + 1.70158 * tt
}
float backInOut (float t) {
    if t < .5 then
        t = t + t
        return (t * t * (3.5949095 * t - 2.5949095)) * .5
    else
        t = t + t - 2
        return (t * t * (3.5949095 * t + 2.5949095) + 2) * .5
    end
}
float elasticIn (float t) {
    if t == 0 then
        return 0
    elseif t == 1 then
        return 1
    else
        return -math.pow(2, 10 * t - 10) * math.sin((t * 10 - 10.75) * PI2 / 3)
    end
}
float elasticOut (float t) {
    if t == 0 then
        return 0
    elseif t == 1 then
        return 1
    else
        return math.pow(2, -10 * t) * math.sin((t * 10 - .75) * PI2 / 3) + 1
    end
}
float elasticInOut (float t) {
    if t == 0 then
        return 0
    elseif t == 1 then
        return 1
    elseif t < 0.5 then
        return -(math.pow(2, 20 * t - 10) * math.sin((t * 20 - 11.125) * PI2 / 4.5)) * .5
    else
        return (math.pow(2, -20 * t + 10) * math.sin((t * 20 - 11.125) * PI2 / 4.5)) * .5 + 1
    end
}
float bounceIn (float t) {
    return 1 - bounceOut(1 - x)
}
float bounceOut (float t) {
    local n1 = 7.5625;
    local d1 = 2.75;
    if t < 1 / d1 then
        return n1 * t * t;
    elseif t < 2 / d1 then
        t = t - 1.5 / d1
        return n1 * t * t + .75;
    elseif t < 2.5 / d1 then
        t = t - 2.25 / d1
        return n1 * t * t + .9375;
    else
        t = t - 2.625 / d1
        return n1 * t * t + .984375;
    end
}
float bounceInOut (float t) {
    if t < .5 then
        return (1 - bounceOut(1 - t + t)) * .5
    else
        return (1 + bounceOut(t + t - 1)) * .5
    end
}

